package com.hfzy.ihk.web.oauth.client.conf;

import com.hfzy.ihk.web.oauth.client.filter.AjaxSessionOutFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.security.oauth2.authserver.AuthorizationServerProperties;
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoRestTemplateFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestOperations;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.AccessTokenConverter;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.web.access.ExceptionTranslationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

/**
 * Created by YANFA on 2019/2/26.
 */
//@EnableWebSecurity
@Slf4j
public class MultiHttpSecurityConfig {


    /**
     * 这个用于类似于app 或者微信端，直接通过token 调用验证，避免走sso登录模式，调到用户登录界面，接口必须api开头
     */

    @Configuration
    @EnableResourceServer
    public static class ApiWebSecurityConfigurationAdapter extends ResourceServerConfigurerAdapter {


        @Value("${security.oauth2.authorization.check-token-access}")
        private String checkTokenAccess;


        public void configure(HttpSecurity http) throws Exception {
            http
                    .antMatcher("/**/api/**")
                    .authorizeRequests().anyRequest().authenticated();

        }

        @Override
        public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
            resources.tokenServices(tokenServices());
        }

        /**
         * 用于app类的远程密码登录
         * @return
         */
        @Bean
        public ResourceServerTokenServices tokenServices() {
            RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
            remoteTokenServices.setCheckTokenEndpointUrl(checkTokenAccess);
            remoteTokenServices.setClientId("ihkapp"); //指定用于外部token 校验的客户端
            remoteTokenServices.setClientSecret("secret");
            remoteTokenServices.setAccessTokenConverter(accessTokenConverter());
            return remoteTokenServices;
        }

        @Bean
        public AccessTokenConverter accessTokenConverter() {
            return new DefaultAccessTokenConverter();
        }


   }



    @Configuration
    @EnableOAuth2Sso //开启单点登录
    public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

        @Value("${security.oauth2.sso.logout-path}")
        private String logoutUrl;
        @Autowired(required = false)
        AjaxSessionOutFilter ajaxSessionOutFilter;

        /**
         * 忽略静态文件
         */
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/frame/**", "/images/**", "/css/**", "/js/**", "/video/**", "/**/favicon.ico");
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .antMatchers("/404", "/error", "/clearSession").permitAll()
                    .anyRequest()
                    .authenticated().and()
                    .csrf().disable()  //关闭csr保护
                    .httpBasic().disable()        //关闭基础验证
                    .addFilterBefore(ajaxSessionOutFilter, ExceptionTranslationFilter.class) //用于解决页面过期以后ajax的处理
                    //开放退出接口跨域
                    .cors().disable() //g关闭跨域的验证
//                     .cors().configurationSource(configurationSource())
//                     .and()
                    .headers().frameOptions().disable().and() //关闭iframe包裹验证  解决iframe 问题
                    .logout().logoutSuccessUrl(logoutUrl).invalidateHttpSession(true);
        }



        /**
         * 退出时清楚缓存接口放开跨域示例
         * @return
         */
        @Bean
        public CorsConfigurationSource configurationSource() {
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            CorsConfiguration config = new CorsConfiguration();
            config.addAllowedOrigin("*");
            config.setAllowCredentials(true);
            config.addAllowedHeader("X-Requested-With");
            config.addAllowedHeader("Content-Type");
            config.addAllowedMethod(HttpMethod.GET);
            source.registerCorsConfiguration("/clearSession", config);
            return source;
        }

        /**
         * 可以用个这个RestTemplate 来进行个服务器之间的调用，由于 开启了EnableOAuth2Sso  这里调用的时候会自动添加token
         * @param resource
         * @param context
         * @return
         */
//        @Bean
//        public OAuth2RestOperations restOperations(OAuth2ProtectedResourceDetails resource, OAuth2ClientContext context) {
//            return new OAuth2RestTemplate(resource, context);
//        }

        @Bean
        public OAuth2RestTemplate restTemplate(UserInfoRestTemplateFactory factory) {
            return factory.getUserInfoRestTemplate();
        }
//
//
//    String personResourceUrl = "http://localhost:9000/person";
//    mav.addObject("person",
//            restOperations.getForObject(personResourceUrl, String.class));

        /**
         * 验证成功监听器
         * @param event
         */

        @EventListener
        public void authSuccessListener(InteractiveAuthenticationSuccessEvent event) {
            log.info("====================》验证成功啦");
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        }

    }



}
